package com.spc.boot.common.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Base64;

/**
 * @author ghliu
 * @create 2019-03-20 19:47
 **/
public final class CoderUtil {

    /**
     * sun 的 BASE64Decoder 在多线程的环境中处理经过 AES 和 Base64 加密的数据时似乎存在问题，
     * 比如 App 请求接口时传过来的 token，需要校验 token，需要用到 BASE64Decoder，这时如果有
     * 多个请求一起过来，线程数大于 1，BASE64Decoder 解密数据时有极大的概率抛出以下异常：
     * javax.crypto.BadPaddingException: Given final block not properly padded
     * 现在的解决办法是替换掉 sun 的 BASE64Decoder 为 java.util.Base64 的
     */
    private static BASE64Encoder base64Encoder;
    private static BASE64Decoder base64Decoder;

    static {
        base64Encoder = new BASE64Encoder();
        base64Decoder = new BASE64Decoder();
    }

    /**
     * base64 编码
     *
     * @param data
     * @return
     */
    public static String encodeBase64(byte[] data) {
        return Base64.getEncoder().encodeToString(data);
//        return base64Encoder.encodeBuffer(data);
    }

    /**
     * base64 解码
     *
     * @param data
     * @return
     * @throws IOException
     */
    public static byte[] decodeBase64(String data) throws IOException {
        return Base64.getDecoder().decode(data);
//        return base64Decoder.decodeBuffer(data);
    }

    /**
     * 2进制数字转换为16进制字符串
     *
     * @param data
     * @return
     */
    public String encodeByteToHex(byte[] data) {
        if (data == null || data.length < 1) {
            return null;
        }

        StringBuffer hex = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            int h = data[i] & 0XFF;
            if (h < 16) {
                hex.append("0");
            }
            hex.append(Integer.toHexString(h));
        }

        return hex.toString();
    }

    /**
     * 16进制字符串转换为2进制数字
     *
     * @param hex
     * @return
     */
    public byte[] decodeHex2Byte(String hex) {
        if (hex == null || "".equals(hex)) {
            return null;
        }

        int length = hex.length() >> 1;
        byte[] data = new byte[length];
        for (int i = 0; i < length; i++) {
            int n = i << 1;
            int height = Integer.valueOf(hex.substring(n, n + 1), 16);
            int low = Integer.valueOf(hex.substring(n + 1, n + 2), 16);
            data[i] = (byte) (height * 16 + low);
        }

        return data;
    }
    
    /**
     * 将ISO编码转UTF8
     * @param str
     * @return
     */
    public static String convert2U8(String str) {
    	if(str == null) return null;
    	try {
			return new String(str.getBytes("ISO8859-1"), "UTF-8") ;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
    	return null;
    }

}
